import re
from typing import List, Any
from functools import partial
from rest_framework import serializers
from pydantic import BaseModel, Field, validator
from bson import ObjectId


KEYWORD_ERROR_MSG = {
    "keywords_default": "请输入敏感词，多个按空格隔开，每个敏感词不超过40字符。",
    "cust_keywords": "请输入敏感词，多个按空格隔开，每个敏感词不超过40字符。"
}


def default_error_msg(key):
    raise serializers.ValidationError(KEYWORD_ERROR_MSG.get(key, "数据必填"))


def str_split_rule(v):
    """字符串 以特定的规则拆分
    """
    rules = '[ \n]'  # 白名单 敏感词 相同的规则 空格 换行
    _v = []
    for item in re.split(rules, v):
        keyword = item.strip()
        if keyword and keyword not in _v:
            _v.append(keyword)
    return _v


class PydanticObjectId(ObjectId):
    """python objectid 校验"""

    @classmethod
    def __get_validators__(cls):
        yield cls.validate

    @classmethod
    def validate(cls, v):
        if not ObjectId.is_valid(v):
            raise TypeError('ObjectId required')
        return ObjectId(v)


class KwdCountSchema(BaseModel):
    """漏洞筛选条件"""

    keyword: str = Field(None, title='关键搜索')


class KeywordMinix:

    @staticmethod
    def check_white_keyword(value):
        if (not value) or (not isinstance(value, str)) or len(value) > 40:
            raise default_error_msg("keywords_default")
        return value

    @classmethod
    def _valid_keywords(cls, values, key):
        data = []
        if not values:
            default_error_msg(key)
        if isinstance(values, list):
            for d in values:
                for v in str_split_rule(d):
                    data.append(cls.check_white_keyword(v))
        elif isinstance(values, str):
            for v in str_split_rule(values):
                data.append(cls.check_white_keyword(v))
        else:
            default_error_msg(key)
        return data


class CustKeywordSchema(BaseModel, KeywordMinix):
    """用户关键词 编辑"""

    cust_keywords: Any = Field(default_factory=partial(default_error_msg, "cust_keywords"), title='用户敏感词')

    @validator('cust_keywords', pre=True)
    def validate_keywords(cls, values):
        if not values:
            return []
        return cls._valid_keywords(values, "cust_keywords")


class WhiteKeywordSchema(BaseModel):
    word: str = Field(None, title='白名单词模糊搜索')
    page: int = Field(1, title='页码')
    count: int = Field(10, title='每页数量')


class WhiteKeywordPostSchema(BaseModel, KeywordMinix):
    white_keywords: Any = Field(default_factory=partial(default_error_msg, "keywords_default"), title='添加白名单敏感词')

    @validator("white_keywords", pre=True)
    def valid_keywords(cls, values):
        return cls._valid_keywords(values, "keywords_default")


class WhiteKeywordDelSchema(BaseModel):
    whitekey_ids: List[PydanticObjectId] = Field(..., title='待删除白名单ID', min_items=1)
